// output.go 包含了一些用于日志输出的工具和函数。
// 这些工具和函数可以用于创建和管理日志文件，
// 并提供了一种方式来将日志消息写入这些文件。

package logrus

import (
	"fmt"
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"github.com/sirupsen/logrus"
	"io"
	"sync"
	"time"
)

type combineWriter struct {
	sync.Mutex
	done    chan struct{}
	writers []io.Writer
}

func NewWriter(outputPaths []string) io.Writer {
	w := &combineWriter{done: make(chan struct{})}
	ws := make([]io.Writer, len(outputPaths))
	for i, outputPath := range outputPaths {
		ws[i] = newLogRotate(outputPath)
	}
	w.writers = ws
	return w
}

func (w *combineWriter) Write(p []byte) (n int, err error) {
	w.Lock()
	defer w.Unlock()
	for _, w := range w.writers {
		_, _ = w.Write(p)
	}
	return len(p), nil
}

func newLogRotate(path string) io.Writer {
	rotateLog, err := rotatelogs.New(
		fmt.Sprintf("%s.%s", path, "%Y%m%d"),
		rotatelogs.WithMaxAge(7*24*time.Hour), rotatelogs.WithRotationTime(24*time.Hour), rotatelogs.WithLinkName(path))
	if err != nil {
		return nil
	}
	return rotateLog
}

type fileHook struct {
	levels        []logrus.Level
	writer        io.Writer
	jsonFormatter *logrus.JSONFormatter
}

func (f *fileHook) Levels() []logrus.Level {
	return f.levels
}

func (f *fileHook) Fire(entry *logrus.Entry) error {
	b, err := f.jsonFormatter.Format(entry)
	if err != nil {
		return err
	}
	_, err = f.writer.Write(b)
	return err
}

func NewFileHook(paths []string, levels []logrus.Level) logrus.Hook {
	return &fileHook{
		levels:        levels,
		writer:        NewWriter(paths),
		jsonFormatter: new(logrus.JSONFormatter),
	}
}
